home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / imagemap / imap_rectangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-03-21  |  15.6 KB  |  524 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Generates clickable image maps.
  5.  *
  6.  * Copyright (C) 1998-1999 Maurits Rijk  lpeek.mrijk@consunet.nl
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  */
  23.  
  24. #include "config.h"
  25.  
  26. #include <stdlib.h>
  27.  
  28. #include "imap_main.h"
  29. #include "imap_misc.h"
  30. #include "imap_object_popup.h"
  31. #include "imap_rectangle.h"
  32. #include "imap_table.h"
  33.  
  34. #include "libgimp/stdplugins-intl.h"
  35.  
  36. #include "rectangle.xpm"
  37.  
  38. static gboolean rectangle_is_valid(Object_t *obj);
  39. static Object_t *rectangle_clone(Object_t *obj);
  40. static void rectangle_assign(Object_t *obj, Object_t *des);
  41. static void rectangle_normalize(Object_t *obj);
  42. static void rectangle_draw(Object_t *obj, GdkWindow *window, GdkGC* gc);
  43. static void rectangle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC* gc);
  44. static MoveSashFunc_t rectangle_near_sash(Object_t *obj, gint x, gint y);
  45. static gboolean rectangle_point_is_on(Object_t *obj, gint x, gint y);
  46. static void rectangle_get_dimensions(Object_t *obj, gint *x, gint *y,
  47.                      gint *width, gint *height);
  48. static void rectangle_resize(Object_t *obj, gint percentage_x, 
  49.                  gint percentage_y);
  50. static void rectangle_move(Object_t *obj, gint dx, gint dy);
  51. static gpointer rectangle_create_info_widget(GtkWidget *frame);
  52. static void rectangle_fill_info_tab(Object_t *obj, gpointer data);
  53. static void rectangle_set_initial_focus(Object_t *obj, gpointer data);
  54. static void rectangle_update(Object_t *obj, gpointer data);
  55. static void rectangle_write_csim(Object_t *obj, gpointer param, 
  56.                  OutputFunc_t output);
  57. static void rectangle_write_cern(Object_t *obj, gpointer param, 
  58.                  OutputFunc_t output);
  59. static void rectangle_write_ncsa(Object_t *obj, gpointer param, 
  60.                  OutputFunc_t output);
  61. static char** rectangle_get_icon_data(void);
  62.  
  63. static ObjectClass_t rectangle_class = {
  64.    N_("Rectangle"),
  65.    NULL,            /* info_dialog */
  66.    NULL,            /* icon */
  67.    NULL,            /* mask */
  68.  
  69.    rectangle_is_valid,
  70.    NULL,            /* rectangle_destruct */
  71.    rectangle_clone,
  72.    rectangle_assign,
  73.    rectangle_normalize,
  74.    rectangle_draw,
  75.    rectangle_draw_sashes,
  76.    rectangle_near_sash,
  77.    rectangle_point_is_on,
  78.    rectangle_get_dimensions,
  79.    rectangle_resize,
  80.    rectangle_move,
  81.    rectangle_create_info_widget,
  82.    rectangle_fill_info_tab,    /* rectangle_update_info_widget */
  83.    rectangle_fill_info_tab,
  84.    rectangle_set_initial_focus,
  85.    rectangle_update,
  86.    rectangle_write_csim,
  87.    rectangle_write_cern,
  88.    rectangle_write_ncsa,
  89.    object_do_popup,
  90.    rectangle_get_icon_data
  91. };
  92.  
  93. Object_t*
  94. create_rectangle(gint x, gint y, gint width, gint height)
  95. {
  96.    Rectangle_t *rectangle = g_new(Rectangle_t, 1);
  97.    rectangle->x = x;
  98.    rectangle->y = y;
  99.    rectangle->width = width;
  100.    rectangle->height = height;
  101.    return object_init(&rectangle->obj, &rectangle_class);
  102. }
  103.  
  104. static void
  105. draw_any_rectangle(GdkWindow *window, GdkGC *gc, gint x, gint y, gint w, 
  106.            gint h)
  107. {
  108.    if (w < 0) {
  109.       x += w;
  110.       w = -w;
  111.    }
  112.    if (h < 0) {
  113.       y += h;
  114.       h = -h;
  115.    }
  116.    draw_rectangle(window, gc, FALSE, x, y, w, h);
  117. }
  118.  
  119. static gboolean
  120. rectangle_is_valid(Object_t *obj)
  121. {
  122.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  123.    return rectangle->width && rectangle->height;
  124. }
  125.  
  126. static Object_t*
  127. rectangle_clone(Object_t *obj)
  128. {
  129.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  130.    Rectangle_t *clone = g_new(Rectangle_t, 1);
  131.  
  132.    clone->x = rectangle->x;
  133.    clone->y = rectangle->y;
  134.    clone->width = rectangle->width;
  135.    clone->height = rectangle->height;
  136.    return &clone->obj;
  137. }
  138.  
  139. static void
  140. rectangle_assign(Object_t *obj, Object_t *des)
  141. {
  142.    Rectangle_t *src_rectangle = ObjectToRectangle(obj);
  143.    Rectangle_t *des_rectangle = ObjectToRectangle(des);
  144.    des_rectangle->x = src_rectangle->x;
  145.    des_rectangle->y = src_rectangle->y;
  146.    des_rectangle->width = src_rectangle->width;
  147.    des_rectangle->height = src_rectangle->height;
  148. }
  149.  
  150. static void
  151. rectangle_normalize(Object_t *obj)
  152. {
  153.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  154.    if (rectangle->width < 0) {
  155.       rectangle->x += rectangle->width;
  156.       rectangle->width = -rectangle->width;
  157.    }
  158.    if (rectangle->height < 0) {
  159.       rectangle->y += rectangle->height;
  160.       rectangle->height = -rectangle->height;
  161.    }
  162. }
  163.  
  164. static void
  165. rectangle_draw(Object_t *obj, GdkWindow *window, GdkGC *gc)
  166. {
  167.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  168.    draw_any_rectangle(window, gc, rectangle->x, rectangle->y,
  169.               rectangle->width, rectangle->height);
  170. }
  171.  
  172. static void
  173. rectangle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC *gc)
  174. {
  175.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  176.    draw_sash(window, gc, rectangle->x, rectangle->y);
  177.    draw_sash(window, gc, rectangle->x + rectangle->width / 2, rectangle->y);
  178.    draw_sash(window, gc, rectangle->x + rectangle->width, rectangle->y);
  179.    draw_sash(window, gc, rectangle->x, rectangle->y + rectangle->height / 2);
  180.    draw_sash(window, gc, rectangle->x + rectangle->width, 
  181.          rectangle->y + rectangle->height / 2);
  182.    draw_sash(window, gc, rectangle->x, rectangle->y + rectangle->height);
  183.    draw_sash(window, gc, rectangle->x + rectangle->width / 2, 
  184.          rectangle->y + rectangle->height);
  185.    draw_sash(window, gc, rectangle->x + rectangle->width, 
  186.          rectangle->y + rectangle->height);
  187. }
  188.  
  189. static void
  190. MoveUpperSash(Object_t *obj, gint dx, gint dy)
  191. {
  192.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  193.    rectangle->y += dy;
  194.    rectangle->height -= dy;
  195. }
  196.  
  197. static void
  198. MoveLeftSash(Object_t *obj, gint dx, gint dy)
  199. {
  200.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  201.    rectangle->x += dx;
  202.    rectangle->width -= dx;
  203. }
  204.  
  205. static void
  206. MoveRightSash(Object_t *obj, gint dx, gint dy)
  207. {
  208.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  209.    rectangle->width += dx;
  210. }
  211.  
  212. static void
  213. MoveLowerSash(Object_t *obj, gint dx, gint dy)
  214. {
  215.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  216.    rectangle->height += dy;
  217. }
  218.  
  219. static void
  220. MoveUpperLeftSash(Object_t *obj, gint dx, gint dy)
  221. {
  222.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  223.    rectangle->x += dx;
  224.    rectangle->y += dy;
  225.    rectangle->width -= dx;
  226.    rectangle->height -= dy;
  227. }
  228.  
  229. static void
  230. MoveUpperRightSash(Object_t *obj, gint dx, gint dy)
  231. {
  232.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  233.    rectangle->y += dy;
  234.    rectangle->width += dx;
  235.    rectangle->height -= dy;
  236. }
  237.  
  238. static void
  239. MoveLowerLeftSash(Object_t *obj, gint dx, gint dy)
  240. {
  241.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  242.    rectangle->x += dx;
  243.    rectangle->width -= dx;
  244.    rectangle->height += dy;
  245. }
  246.  
  247. static void
  248. MoveLowerRightSash(Object_t *obj, gint dx, gint dy)
  249. {
  250.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  251.    rectangle->width += dx;
  252.    rectangle->height += dy;
  253. }
  254.  
  255. static MoveSashFunc_t
  256. rectangle_near_sash(Object_t *obj, gint x, gint y)
  257. {
  258.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  259.    if (near_sash(rectangle->x, rectangle->y, x, y))
  260.       return MoveUpperLeftSash;
  261.    else if (near_sash(rectangle->x + rectangle->width / 2, rectangle->y, x, y))
  262.       return MoveUpperSash;
  263.    else if (near_sash(rectangle->x + rectangle->width, rectangle->y, x, y))
  264.       return MoveUpperRightSash;
  265.    else if (near_sash(rectangle->x, rectangle->y + rectangle->height / 2, 
  266.               x, y))
  267.       return MoveLeftSash;
  268.    else if (near_sash(rectangle->x + rectangle->width, 
  269.               rectangle->y + rectangle->height / 2, x, y))
  270.       return MoveRightSash;
  271.    else if (near_sash(rectangle->x, rectangle->y + rectangle->height, x, y))
  272.       return MoveLowerLeftSash;
  273.    else if (near_sash(rectangle->x + rectangle->width / 2, 
  274.               rectangle->y + rectangle->height, x, y))
  275.       return MoveLowerSash;
  276.    else if (near_sash(rectangle->x + rectangle->width, 
  277.               rectangle->y + rectangle->height, x, y))
  278.       return MoveLowerRightSash;
  279.    return NULL;
  280. }
  281.  
  282. static gboolean
  283. rectangle_point_is_on(Object_t *obj, gint x, gint y)
  284. {
  285.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  286.    return x >= rectangle->x && x <= rectangle->x + rectangle->width &&
  287.       y >= rectangle->y && y <= rectangle->y + rectangle->height;
  288. }
  289.  
  290. static void 
  291. rectangle_get_dimensions(Object_t *obj, gint *x, gint *y,
  292.              gint *width, gint *height)
  293. {
  294.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  295.    *x = rectangle->x;
  296.    *y = rectangle->y;
  297.    *width = rectangle->width;
  298.    *height = rectangle->height;
  299. }
  300.  
  301. static void 
  302. rectangle_resize(Object_t *obj, gint percentage_x, gint percentage_y)
  303. {
  304.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  305.    rectangle->x = rectangle->x * percentage_x / 100;
  306.    rectangle->y = rectangle->y * percentage_y / 100;
  307.    rectangle->width = rectangle->width * percentage_x / 100;
  308.    rectangle->height = rectangle->height * percentage_y / 100;
  309. }
  310.  
  311. static void
  312. rectangle_move(Object_t *obj, gint dx, gint dy)
  313. {
  314.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  315.    rectangle->x += dx;
  316.    rectangle->y += dy;
  317. }
  318.  
  319. typedef struct {
  320.    Object_t  *obj;
  321.    GtkWidget *x;
  322.    GtkWidget *y;
  323.    GtkWidget *width;
  324.    GtkWidget *height;
  325. } RectangleProperties_t;
  326.  
  327. static void
  328. x_changed_cb(GtkWidget *widget, gpointer data)
  329. {
  330.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  331.    gint x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  332.    ObjectToRectangle(obj)->x = x;
  333.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  334. }
  335.  
  336. static void
  337. y_changed_cb(GtkWidget *widget, gpointer data)
  338. {
  339.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  340.    gint y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  341.    ObjectToRectangle(obj)->y = y;
  342.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  343. }
  344.  
  345. static void
  346. width_changed_cb(GtkWidget *widget, gpointer data)
  347. {
  348.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  349.    gint width = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  350.    ObjectToRectangle(obj)->width = width;
  351.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  352. }
  353.  
  354. static void
  355. height_changed_cb(GtkWidget *widget, gpointer data)
  356. {
  357.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  358.    gint height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  359.    ObjectToRectangle(obj)->height = height;
  360.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  361. }
  362.  
  363. static gpointer
  364. rectangle_create_info_widget(GtkWidget *frame)
  365. {
  366.    RectangleProperties_t *props = g_new(RectangleProperties_t, 1);
  367.    GtkWidget *table;
  368.    gint max_width = get_image_width();
  369.    gint max_height = get_image_height();
  370.  
  371.    table = gtk_table_new(4, 3, FALSE);
  372.    gtk_container_add(GTK_CONTAINER(frame), table);
  373.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  374.  
  375.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  376.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  377.    gtk_widget_show(table);
  378.    
  379.    create_label_in_table(table, 0, 0, _("Upper left x:"));
  380.    props->x = create_spin_button_in_table(table, 0, 1, 1, 0, max_width - 1);
  381.    gtk_signal_connect(GTK_OBJECT(props->x), "changed", 
  382.               (GtkSignalFunc) x_changed_cb, (gpointer) props);
  383.    create_label_in_table(table, 0, 2, _("pixels"));
  384.  
  385.    create_label_in_table(table, 1, 0, _("Upper left y:"));
  386.    props->y = create_spin_button_in_table(table, 1, 1, 1, 0, max_height - 1);
  387.    gtk_signal_connect(GTK_OBJECT(props->y), "changed", 
  388.               (GtkSignalFunc) y_changed_cb, (gpointer) props);
  389.    create_label_in_table(table, 1, 2, _("pixels"));
  390.  
  391.    create_label_in_table(table, 2, 0, _("Width:"));
  392.    props->width = create_spin_button_in_table(table, 2, 1, 1, 1, max_width);
  393.    gtk_signal_connect(GTK_OBJECT(props->width), "changed", 
  394.               (GtkSignalFunc) width_changed_cb, (gpointer) props);
  395.    create_label_in_table(table, 2, 2, _("pixels"));
  396.  
  397.    create_label_in_table(table, 3, 0, _("Height:"));
  398.    props->height = create_spin_button_in_table(table, 3, 1, 1, 1, max_height);
  399.    gtk_signal_connect(GTK_OBJECT(props->height), "changed", 
  400.               (GtkSignalFunc) height_changed_cb, (gpointer) props);
  401.    create_label_in_table(table, 3, 2, _("pixels"));
  402.  
  403.    return props;
  404. }
  405.  
  406. static void 
  407. rectangle_fill_info_tab(Object_t *obj, gpointer data)
  408. {
  409.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  410.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  411.  
  412.    props->obj = obj;
  413.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->x), rectangle->x);
  414.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->y), rectangle->y);
  415.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->width), rectangle->width);
  416.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->height), 
  417.                  rectangle->height);
  418. }
  419.  
  420. static void 
  421. rectangle_set_initial_focus(Object_t *obj, gpointer data)
  422. {
  423.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  424.    gtk_widget_grab_focus(props->x);
  425. }
  426.  
  427. static void 
  428. rectangle_update(Object_t* obj, gpointer data)
  429. {
  430.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  431.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  432.  
  433.    rectangle->x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->x));
  434.    rectangle->y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->y));
  435.    rectangle->width = gtk_spin_button_get_value_as_int(
  436.       GTK_SPIN_BUTTON(props->width));
  437.    rectangle->height = gtk_spin_button_get_value_as_int(
  438.       GTK_SPIN_BUTTON(props->height));
  439. }
  440.  
  441. static void
  442. rectangle_write_csim(Object_t *obj, gpointer param, OutputFunc_t output)
  443. {
  444.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  445.    output(param, "\"rect\" coords=\"%d,%d,%d,%d\"", rectangle->x, rectangle->y,
  446.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  447. }
  448.  
  449. static void
  450. rectangle_write_cern(Object_t *obj, gpointer param, OutputFunc_t output)
  451. {
  452.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  453.    output(param, "rect (%d,%d) (%d,%d)", rectangle->x, rectangle->y,
  454.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  455. }
  456.  
  457. static void
  458. rectangle_write_ncsa(Object_t *obj, gpointer param, OutputFunc_t output)
  459. {
  460.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  461.    output(param, "rect %s %d,%d %d,%d", obj->url,
  462.       rectangle->x, rectangle->y,
  463.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  464. }
  465.  
  466. static char**
  467. rectangle_get_icon_data(void)
  468. {
  469.    return rectangle_xpm;
  470. }
  471.  
  472. static gboolean
  473. rectangle_factory_finish(Object_t *obj, gint x, gint y)
  474. {
  475.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  476.  
  477.    rectangle->width = x - rectangle->x;
  478.    rectangle->height = y - rectangle->y;
  479.  
  480.    rectangle_normalize(obj);
  481.    
  482.    return TRUE;
  483. }
  484.  
  485. static Object_t*
  486. rectangle_factory_create_object(gint x, gint y)
  487. {
  488.    return create_rectangle(x, y, 0, 0);
  489. }
  490.  
  491. static void
  492. rectangle_factory_set_xy(Object_t *obj, guint state, gint x, gint y)
  493. {
  494.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  495.  
  496.    rectangle->width = x - rectangle->x;
  497.    rectangle->height = y - rectangle->y;
  498.  
  499.    if (state & GDK_SHIFT_MASK){
  500.       gint width = abs(rectangle->width);
  501.       gint height = abs(rectangle->height);
  502.       if (width < height)
  503.      rectangle->height = (rectangle->height < 0) ? -width : width;
  504.       else
  505.      rectangle->width = (rectangle->width < 0) ? -height : height;
  506.    }
  507.  
  508.    main_set_dimension(rectangle->width, rectangle->height);
  509. }
  510.  
  511. static ObjectFactory_t rectangle_factory = {
  512.    NULL,            /* Object pointer */
  513.    rectangle_factory_finish,
  514.    NULL,            /* Cancel func */
  515.    rectangle_factory_create_object,
  516.    rectangle_factory_set_xy
  517. };
  518.  
  519. ObjectFactory_t*
  520. get_rectangle_factory(guint state)
  521. {
  522.    return &rectangle_factory;
  523. }
  524.